from pprint import pprint

import xmltodict
import typing as tp

from core.services import get_vm_conn
from eve.models.libvirt_models import BaseModel
from eve.models.libvirt_models.network import Node


class Name(Node):
    pass

    def to_xml(self):
        return f'<name>{self.value__}</name>'


class Memory(Node):
    unit: str = 'MB'

    def to_xml(self):
        return f'''<memory unit='{self.unit}'>{self.value__}</memory>'''


class Vcpu(Node):
    placement: str = 'static'

    def to_xml(self):
        return f'''<vcpu placement='{self.placement}'>{self.value__}</vcpu>'''


class Os(Node):
    type_arch: str = 'x86_64'

    def to_xml(self):
        return f'''<os><type arch='{self.type_arch}' machine='pc-i440fx-rhel7.0.0'>hvm</type><boot dev='hd'/></os>'''


class Features(Node):
    value__: tp.List[str] = ['acpi', 'apic']

    def to_xml(self):
        s = '<features>'
        for _ in self.value__:
            s += f'<{_}/>'
        s += '</features>'
        return s


class On_(Node):

    def to_xml(self):
        return f'''<on_poweroff>destroy</on_poweroff><on_reboot>destroy</on_reboot><on_crash>destroy</on_crash>'''


class Pm(Node):

    def to_xml(self):
        return f'''<pm><suspend-to-mem enabled='no'/><suspend-to-disk enabled='no'/></pm>'''


class Emulator(Node):

    def to_xml(self):
        return f'''<emulator>/usr/libexec/qemu-kvm</emulator>'''


class Disk(Node):
    drive_name: str = 'qemu'
    drive_type: str = 'qcow2'
    target_dev: str = 'hda'
    target_bus: str = 'ide'

    def to_xml(self):
        return f'''<disk type='file' device='disk'><driver name='{self.drive_name}' type='{self.drive_type}'/><source file='{self.value__}'/><target dev='{self.target_dev}' bus='{self.target_bus}'/></disk>'''


class Interface(Node):
    network_name: str = 'default'
    bridge_name: str = 'virbr0'

    # value__: tp.List[str] = ['interface']

    def to_xml(self):
        return f'''<interface type='network'><source network='{self.network_name}' bridge='{self.bridge_name}'/></interface>'''


class Console(Node):

    def to_xml(self):
        return f'''<console type='pty'><target type='serial'/></console>'''


class Devices(Node):
    emulator: Emulator
    disk: Disk
    interfaces: tp.List[Interface] = [Interface()]
    console: Console

    def to_xml(self):
        s = f'''<devices>'''
        s += self.emulator.to_xml()
        s += self.disk.to_xml()
        for _ in self.interfaces:
            s += _.to_xml()
        s += self.console.to_xml()
        s += f'''</devices>'''
        return s


class Domain(BaseModel):
    name: Name
    memory: Memory
    vcpu: Vcpu
    os: Os
    features: Features
    on_: On_
    pm: Pm
    devices: Devices

    def to_xml(self):
        s = ''
        s += '<domain type="kvm">'
        s += self.name.to_xml()
        s += self.memory.to_xml()
        s += self.vcpu.to_xml()
        s += self.os.to_xml()
        s += self.features.to_xml()
        s += self.on_.to_xml()
        s += self.pm.to_xml()
        s += self.devices.to_xml()
        s += '</domain>'

        return s

    @staticmethod
    def from_xml(xmlDesc):
        d = xmltodict.parse(xmlDesc)['domain']
        dom = Domain(
            name=Name(value__=d['name']),
            memory=Memory(value__=d['memory']['#text']),
            vcpu=Vcpu(value__=d['vcpu']['#text']),
            os=Os(type_arch=d['os']['type']['@arch']),

            features=Features(acpi=d['features']['acpi'], apic=d['features']['apic']),
            # devices=Devices(emulator=d['devices']['emulator'], disk=d['devices']['disk'], interfaces=d['devices']['interface'], console=d['devices']['console'])
            on_=On_(),
            pm=Pm(),
            devices=Devices(emulator=Emulator(), disk=Disk(value__=d['devices']['disk']['source']['@file']), console=Console())
        )
        return dom


# if __name__ == '__main__':
ini_domain = Domain(
    name=Name(value__='1'),
    memory=Memory(value__='1024'),
    vcpu=Vcpu(value__='1'),
    os=Os(),
    features=Features(),
    on_=On_(),
    pm=Pm(),
    devices=Devices(emulator=Emulator(), disk=Disk(value__='/root/CentOS-7-x86_64-GenericCloud-2009.qcow2'), console=Console())
    )
    # GET /interfaces/?virtual_machine_instance_id=35
    # POST /interfaces/?virtual_machine_instance_id=35
    # GET /interfaces/0?virtual_machine_instance_id=35
    # PATCH /interfaces/0?virtual_machine_instance_id=35 {ip_address, ip_netmask}
    # DELETE /virtual_machine_instances/35/interfaces/0?virtual_machine_instance_id=35 {ip_address, ip_netmask}

    # ini_domain.devices.interfaces.append(Interface(network_name='default', bridge_name='123??'))
    # ini_domain.devices.interfaces.append(Interface(network_name='default', bridge_name='1234??'))
    # pprint(ini_domain.to_xml())
